//// Copyright 2008 David Mitchell
//// Released under the MIT License

//using System;
//using System.Reflection;
//using System.Runtime.InteropServices;

//namespace NSDuctTape
//{
//  internal class ObjectiveCMethod
//  {
//    public ObjectiveCMethod(string name, MethodInfo implementation)
//    {
//      if (name == null)
//        throw new ArgumentNullException("name");
//      if (name.Length == 0)
//        throw new ArgumentException("name cannot be empty.", "name");
//      if (implementation == null)
//        throw new ArgumentNullException("implementation");

//      _name = name;
//      _types = name == "respondsToSelector:" ? "c12@0:4:8" : name == "methodSignatureForSelector:" ? "@@::" : GenerateTypeString(implementation);
//      _implementation = implementation.MethodHandle.GetFunctionPointer();
//    }

//    public ObjectiveCMethod(string name, ConstructorInfo implementation)
//    {
//      if (name == null)
//        throw new ArgumentException("name");
//      if (name.Length == 0)
//        throw new ArgumentException("name cannot be empty.", "name");
//      if (implementation == null)
//        throw new ArgumentNullException("implementation");

//      _name = name;
//      _types = GenerateTypeString(implementation);
//      _implementation = typeof(ObjectiveCMethod).GetMethod("InvokeConstructor", BindingFlags.Static | BindingFlags.NonPublic).MethodHandle.GetFunctionPointer();
//    }

//    public string Name { get { return _name; } }
//    public string Types { get { return _types; } }
//    public IntPtr Implementation { get { return _implementation; } }

//    public static string GenerateTypeString<T>(T info) where T : MethodBase
//    {
//      string types = info is MethodInfo ?
//        GetTypeStringForType((info as MethodInfo).ReturnType) :
//        info is ConstructorInfo ?
//        "@" :
//        "v";

//      // Every method takes a pointer to an instance and a selector.
//      types += "@:";

//      foreach (ParameterInfo parameter in info.GetParameters())
//        types += GetTypeStringForType(parameter.ParameterType);

//      return types;
//    }

//    internal ObjectiveCMethod(IntPtr nativeInfo)
//    {
//      ObjectiveCMethodInfo info = MarshalUtility.PtrToStructure<ObjectiveCMethodInfo>(nativeInfo);
//      _name = Marshal.PtrToStringAnsi(info.name);
//      _types = Marshal.PtrToStringAnsi(info.types);
//      _implementation = info.implementation;
//    }

//    public static string GetTypeStringForType(Type type)
//    {
//      // Type encodings have been pulled from http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC/Articles/chapter_5_section_7.html
//      string str;
//      if (type == typeof(char))
//        str = "c";
//      else if (type == typeof(int))
//        str = "i";
//      else if (type == typeof(short))
//        str = "s";
//      else if (type == typeof(long))
//        str = "l";
//      // Leaving out typeof(long long) => "q"
//      else if (type == typeof(byte))
//        str = "C";
//      else if (type == typeof(uint))
//        str = "I";
//      else if (type == typeof(ushort))
//        str = "S";
//      else if (type == typeof(ulong))
//        str = "L";
//      // Leaving out typeof(unsigned long long) => "Q"
//      else if (type == typeof(float))
//        str = "f";
//      else if (type == typeof(double))
//        str = "d";
//      else if (type == typeof(bool))
//        str = "B";
//      else if (type == typeof(void))
//        str = "v";
//      else if (type == typeof(ObjectiveCClass))
//        str = "#";
//      else
//        str = "@";

//      // Things that have been left out:
//      // Selector => ":"
//      // Array => "[array-type]" where array-type is the number of elements followed by a type
//      // Structure => "{structurename=typeencoding}"
//      // Union => "(unionname=typeencoding)"
//      // bit field => "bNumberOfBits"
//      // pointer => "^type"
//      // unknown type => "?"

//      // Protocol support:
//      // const => "r"
//      // in => "n"
//      // in and out => "N"
//      // out => "o"
//      // by copy => "O"
//      // by ref => "R"
//      // one way => "V"

//      return str;
//    }

//    public static Type GetTypeForTypeString(string str)
//    {
//      Type type;
//      if (str == "c")
//        type = typeof(char);
//      else if (str == "i")
//        type = typeof(int);
//      else if (str == "s")
//        type = typeof(short);
//      else if (str == "l")
//        type = typeof(long);
//      // Leaving out "q" => typeof(long long)
//      else if (str == "C")
//        type = typeof(byte);
//      else if (str == "I")
//        type = typeof(uint);
//      else if (str == "S")
//        type = typeof(ushort);
//      else if (str == "L")
//        type = typeof(ulong);
//      // Leaving out "Q" => typeof(unsigned long long)
//      else if (str == "f")
//        type = typeof(float);
//      else if (str == "d")
//        type = typeof(double);
//      else if (str == "B")
//        type = typeof(bool);
//      else if (str == "v")
//        type = typeof(void);
//      else if (str == "#")
//        type = typeof(ObjectiveCClass);
//      else
//        type = typeof(IntPtr);

//      return type;
//    }

//    string _name;
//    string _types;
//    IntPtr _implementation;
//  }
//}
